* { box-sizing: border-box; margin: 0; padding: 0; } /* Hidden-field helper for demo mode */ .hidden-field { display: none !important; } :root { --primary: #ff6b35; --primary-dark: #e55a2b; --dark: #1a1a2e; --light: #f8f9fa; --gray: #6c757d; } body { font-family: 'Segoe UI', system-ui, sans-serif; background: var(--dark); color: white; min-height: 100vh; } .header { background: rgba(0,0,0,0.3); padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(255,255,255,0.1); } .logo { font-size: 1.5rem; font-weight: bold; color: var(--primary); } .container { max-width: 1400px; margin: 0 auto; padding: 2rem; display: grid; grid-template-columns: 350px 1fr; gap: 2rem; } .controls { background: rgba(255,255,255,0.05); border-radius: 12px; padding: 1.5rem; height: fit-content; } .controls h2 { color: var(--primary); margin-bottom: 1.5rem; font-size: 1.2rem; } .form-group { margin-bottom: 1.2rem; } .form-group label { display: block; margin-bottom: 0.5rem; font-size: 0.85rem; color: rgba(255,255,255,0.7); } .form-group input, .form-group select { width: 100%; padding: 0.7rem; border: 1px solid rgba(255,255,255,0.2); border-radius: 6px; background: rgba(255,255,255,0.1); color: white; font-size: 0.95rem; } .form-group select option { background: #1a1a2e; color: white; } .form-group input::placeholder { color: rgba(255,255,255,0.4); } .form-group input:focus, .form-group select:focus { outline: none; border-color: var(--primary); } .theme-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; } .theme-option { padding: 0.6rem; border: 2px solid transparent; border-radius: 8px; cursor: pointer; text-align: center; font-size: 0.8rem; transition: all 0.2s; } .theme-option:hover { transform: scale(1.02); } .theme-option.selected { border-color: var(--primary); background: rgba(255,107,53,0.2); } .theme-1 { background: linear-gradient(135deg, #1a1a2e, #ff6b35); } .theme-2 { background: linear-gradient(135deg, #ffffff, #3498db); color: #333; } .theme-3 { background: linear-gradient(135deg, #ff6b35, #27ae60); } .theme-4 { background: linear-gradient(135deg, #1a1a2e, #ffd700); } .theme-5 { background: linear-gradient(135deg, #e74c3c, #f39c12); } .preview-frame { background: white; border-radius: 12px; overflow: hidden; min-height: 600px; position: relative; } .preview-header { background: #f0f0f0; padding: 0.5rem 1rem; display: flex; align-items: center; gap: 0.5rem; border-bottom: 1px solid #ddd; } .preview-dot { width: 12px; height: 12px; border-radius: 50%; } .dot-red { background: #ff5f56; } .dot-yellow { background: #ffbd2e; } .dot-green { background: #27c93f; } .preview-url { background: white; flex: 1; padding: 0.4rem 0.8rem; border-radius: 4px; font-size: 0.8rem; color: #666; margin-left: 1rem; } .preview-content { height: calc(100% - 40px); overflow: auto; } .preview-content iframe { width: 100%; height: 100%; border: none; } .actions { margin-top: 1.5rem; display: flex; gap: 1rem; } .btn { flex: 1; padding: 0.8rem 1rem; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 0.95rem; transition: all 0.2s; } .btn-primary { background: var(--primary); color: white; } .btn-primary:hover { background: var(--primary-dark); } .btn-secondary { background: rgba(255,255,255,0.1); color: white; } .btn-secondary:hover { background: rgba(255,255,255,0.2); } .success-message { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--dark); border: 2px solid var(--primary); border-radius: 12px; padding: 2rem; text-align: center; z-index: 1000; box-shadow: 0 20px 60px rgba(0,0,0,0.5); } .success-message.show { display: block; } .success-message h3 { color: var(--primary); margin-bottom: 1rem; } .success-message p { margin-bottom: 1rem; color: rgba(255,255,255,0.7); } .overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); z-index: 999; } .overlay.show { display: block; } .image-preview { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-top: 1rem; padding: 0.75rem; background: rgba(0,0,0,0.2); border-radius: 8px; } .image-preview img { width: 100%; height: 60px; object-fit: cover; border-radius: 4px; } .image-preview-label { font-size: 0.75rem; color: rgba(255,255,255,0.5); margin-bottom: 0.25rem; } @media (max-width: 900px) { .container { grid-template-columns: 1fr; } .preview-frame { min-height: 400px; } }
Page loading...
Website Builder

🎨 Customize Your Site

Bold Modern
Clean Pro
Vibrant
Luxury
Friendly
📸 Stock Images for This Service
🖼️ Add Your Own Photos (Optional)

Upload your own photos to use instead of stock images. Select each slot below and upload the matching image.

https://yoursite.atlas-automation.co/preview

✅ Website Saved!

Your design has been saved. We'll build your custom website and contact you within 24 hours.

let selectedTheme = 'theme-1'; // Fetch custom images from Airtable (fully automated) async function getCustomImages() { try { const response = await fetch('https://atlas-automation.co/api/custom-images'); if (response.ok) { return await response.json(); } } catch(e) {} return {}; } // AUTO-LOAD CUSTOM IMAGES FROM AIRTABLE const AIRTABLE_API = "/api/airtable"; async function loadCustomImages() { try { const resp = await fetch("/api/airtable?table=tblrjkZ7ZLBjR0Ntb?maxRecords=100", { headers: { "Content-Type": "application/json" } }); const data = await resp.json(); const custom = {}; for (const record of data.records) { const f = record.fields; if (f["Service Type"] && f["Image Slot"] && f["Image URL"]) { const svc = f["Service Type"]; const slot = f["Image Slot"]; if (!custom[svc]) custom[svc] = { hero: "", services: ["", "", "", "", ""] }; if (slot === "hero") custom[svc].hero = f["Image URL"]; else { const idx = parseInt(slot.replace("service", "")) - 1; if (idx >= 0 && idx < 5) custom[svc].services[idx] = f["Image URL"]; } } } // Merge with stockImages - custom overwrites default for (const svc of Object.keys(custom)) { if (custom[svc].hero) stockImages[svc].hero = custom[svc].hero; for (let i = 0; i < 5; i++) { if (custom[svc].services[i]) stockImages[svc].services[i] = custom[svc].services[i]; } } console.log("Custom images loaded from Airtable"); } catch(e) { console.log("Using default images:", e.message); } } // Load custom images on startup loadCustomImages(); // Stock images for each service type const stockImages = { plumbing: { hero: "https://images.unsplash.com/photo-1585704032915-c3400ca199e7?w=1200", services: [ "https://i.ibb.co/Q7VTfCf7/Plumber-service-1-fixing-a-leaking-pipe.png", "https://i.ibb.co/JwMwr4m5/Plumber-service-2-cleaning-drain.png", "https://i.ibb.co/hRKrM0Xr/Plumber-service-3-water-heater-install.png", "https://i.ibb.co/bRWN80Fk/plumber-service-4-installing-PVC-pipe.png", "https://i.ibb.co/FkzcL06F/Plumber-service-5-working-on-bathroom-remodel.png" ] }, hvac: { hero: "https://images.unsplash.com/photo-1631545806609-48e6335a4c2c?w=1200", services: [ "https://images.unsplash.com/photo-1631545806609-48e6335a4c2c?w=400", "https://images.unsplash.com/photo-1621905251189-08b45d6a269e?w=400", "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=400", "https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=400", "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400" ] }, roofing: { hero: "https://images.unsplash.com/photo-1632832482219-a1a5edc9f08d?w=1200", services: [ "https://images.unsplash.com/photo-1632832482219-a1a5edc9f08d?w=400", "https://images.unsplash.com/photo-1605116683261-ec156b0f2d5f?w=400", "https://images.unsplash.com/photo-1600585152220-90363fe7e115?w=400", "https://images.unsplash.com/photo-1628069770292-4838b2b9fd8d?w=400", "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=400" ] }, electrical: { hero: "https://images.unsplash.com/photo-1621905251189-08b45d6a269e?w=1200", services: [ "https://images.unsplash.com/photo-1621905251189-08b45d6a269e?w=400", "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400", "https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=400", "https://images.unsplash.com/photo-1508514177221-188b1cf2f26f?w=400", "https://images.unsplash.com/photo-1523784321324-09bf1b370e5c?w=400" ] }, pool: { hero: "https://images.unsplash.com/photo-1576013551627-0cc20b96c2a7?w=1200", services: [ "https://images.unsplash.com/photo-1576013551627-0cc20b96c2a7?w=400", "https://images.unsplash.com/photo-1576013551627-0cc20b96c2a7?w=400", "https://images.unsplash.com/photo-1576013551627-0cc20b96c2a7?w=400", "https://images.unsplash.com/photo-1576013551627-0cc20b96c2a7?w=400", "https://images.unsplash.com/photo-1576013551627-0cc20b96c2a7?w=400" ] }, painting: { hero: "https://images.unsplash.com/photo-1562259949-e8e7689d7828?w=1200", services: [ "https://images.unsplash.com/photo-1562259949-e8e7689d7828?w=400", "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400", "https://images.unsplash.com/photo-1562259949-e8e7689d7828?w=400", "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=400", "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400" ] }, flooring: { hero: "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=1200", services: [ "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400", "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400", "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400", "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400", "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400" ] }, appliance: { hero: "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=1200", services: [ "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=400", "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=400", "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=400", "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=400", "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=400" ] }, pest: { hero: "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=1200", services: [ "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=400", "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=400", "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=400", "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=400", "https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=400" ] }, siding: { hero: "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=1200", services: [ "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400", "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400", "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400", "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400", "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400" ] }, masonry: { hero: "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=1200", services: [ "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=400", "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=400", "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=400", "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=400", "https://images.unsplash.com/photo-1600566752355-35792bedcfea?w=400" ] }, landscaping: { hero: "https://images.unsplash.com/photo-1558904541-fa88e93a6f97?w=1200", services: [ "https://images.unsplash.com/photo-1558904541-fa88e93a6f97?w=400", "https://images.unsplash.com/photo-1598902108854-10e335adac99?w=400", "https://images.unsplash.com/photo-1558618047-f4b511d88421?w=400", "https://images.unsplash.com/photo-1585320806297-9794b3e4eeae?w=400", "https://images.unsplash.com/photo-1605116683261-ec156b0f2d5f?w=400" ] }, handyman: { hero: "https://images.unsplash.com/photo-1581578731548-c64695ccb2ab?w=1200", services: [ "https://images.unsplash.com/photo-1581578731548-c64695ccb2ab?w=400", "https://images.unsplash.com/photo-1581578731548-c64695ccb2ab?w=400", "https://images.unsplash.com/photo-1581578731548-c64695ccb2ab?w=400", "https://images.unsplash.com/photo-1581578731548-c64695ccb2ab?w=400", "https://images.unsplash.com/photo-1581578731548-c64695ccb2ab?w=400" ] }, cleaning: { hero: "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=1200", services: [ "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400", "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400", "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400", "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400", "https://images.unsplash.com/photo-1589939705384-5185137a7f0f?w=400" ] }, carpet: { hero: "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=1200", services: [ "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=400", "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=400", "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=400", "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=400", "https://images.unsplash.com/photo-1524758631624-e2822e304c36?w=400" ] } }; // Theme configs const themes = { 'theme-1': { name: 'Bold Modern', bg: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)', accent: '#ff6b35', text: '#ffffff', secondary: '#0f3460' }, 'theme-2': { name: 'Clean Professional', bg: 'linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%)', accent: '#3498db', text: '#2c3e50', secondary: '#ecf0f1' }, 'theme-3': { name: 'Vibrant Service', bg: 'linear-gradient(135deg, #fff 0%, #fff5e6 100%)', accent: '#ff6b35', text: '#333333', secondary: '#e8f5e9' }, 'theme-4': { name: 'Luxury Premium', bg: 'linear-gradient(135deg, #1a1a2e 0%, #2c2c54 100%)', accent: '#ffd700', text: '#ffffff', secondary: '#3d3d5c' }, 'theme-5': { name: 'Friendly Local', bg: 'linear-gradient(135deg, #fff5f5 0%, #fff 100%)', accent: '#e74c3c', text: '#2c3e50', secondary: '#ffeaa7' } }; function selectTheme(el) { // existing code document.querySelectorAll('.theme-option').forEach(t => t.classList.remove('selected')); el.classList.add('selected'); selectedTheme = el.dataset.theme; previewSite(); } function updateImagePreview() { const service = document.getElementById('serviceType').value; const images = stockImages[service]; const container = document.getElementById('imagePreview'); let html = ``; images.services.slice(0, 2).forEach(img => { html += ``; }); container.innerHTML = html; } function getServiceOptions(service) { const options = { 'plumbing': ['Emergency Repairs', 'Drain Cleaning', 'Water Heater Install', 'Pipe Replacement', 'Bathroom Remodel'], 'hvac': ['AC Repair', 'Heating Service', 'AC Installation', 'Maintenance', 'Indoor Air Quality'], 'roofing': ['Roof Repair', 'Roof Replacement', 'Storm Damage', 'Gutter Installation', 'Inspection'], 'electrical': ['Electrical Repairs', 'Panel Upgrades', 'Lighting Install', 'Safety Inspections', 'EV Chargers'], 'pool': ['Pool Cleaning', 'Pool Maintenance', 'Pool Repairs', 'Pool Opening/Closing', 'Chemical Services'], 'painting': ['Interior Painting', 'Exterior Painting', 'Cabinet Refinishing', 'Deck Staining', 'Commercial'], 'flooring': ['Hardwood Flooring', 'Tile Installation', 'Carpet Install', 'Vinyl/LVP', 'Floor Repair'], 'appliance': ['Refrigerator Repair', 'Washer/Dryer Repair', 'Dishwasher Repair', 'Oven/Range Repair', 'AC Appliance Repair'], 'pest': ['Termite Control', 'Bed Bug Treatment', 'Rodent Control', 'Mosquito Treatment', 'General Pest Control'], 'siding': ['Vinyl Siding', 'Fiber Cement Siding', 'Siding Repair', 'Siding Replacement', 'Siding Painting'], 'masonry': ['Brick Repair', 'Concrete Work', 'Patio Install', 'Retaining Walls', 'Chimney Repair'], 'landscaping': ['Lawn Maintenance', 'Tree Service', 'Landscape Design', 'Irrigation', 'Outdoor Lighting'], 'handyman': ['General Repairs', 'Furniture Assembly', 'TV Mounting', 'Door/Window Repair', 'Minor Plumbing'], 'cleaning': ['House Cleaning', 'Deep Cleaning', 'Move In/Out Cleaning', 'Office Cleaning', 'Carpet Cleaning'], 'carpet': ['Carpet Cleaning', 'Steam Cleaning', 'Stain Removal', 'Carpet Repair', 'Upholstery Cleaning'] }; return options[service] || options['plumbing']; } // Slot-by-slot image upload function generateSlotUploads() { const serviceType = document.getElementById('serviceType').value; let services = getServiceOptions(serviceType) || []; const container = document.getElementById('slotUploads'); // Slots: hero + 5 services + team + projects const slots = [ { id: 'hero', label: 'Hero Image (main banner)' }, { id: 'service1', label: 'Service 1: ' + services[0] }, { id: 'service2', label: 'Service 2: ' + services[1] }, { id: 'service3', label: 'Service 3: ' + services[2] }, { id: 'service4', label: 'Service 4: ' + services[3] }, { id: 'service5', label: 'Service 5: ' + (services[4] || '') }, { id: 'team1', label: 'Team Member 1 (photo)' }, { id: 'team2', label: 'Team Member 2 (photo)' }, { id: 'project1', label: 'Completed Project 1 (photo)' }, { id: 'project2', label: 'Completed Project 2 (photo)' }, { id: 'project3', label: 'Completed Project 3 (photo)' } ]; let html = ''; slots.forEach(slot => { html += `
No image
`; }); container.innerHTML = html; } function handleSlotImage(input, slotId) { const file = input.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { const preview = document.getElementById('preview_' + slotId); preview.innerHTML = '✅ ' + file.name; preview.style.color = '#27ae60'; // Store the image data if (!window.customSlotImages) window.customSlotImages = {}; window.customSlotImages[slotId] = e.target.result; const debugBox = document.getElementById('debugInfo'); if (debugBox) { debugBox.innerHTML = 'Debug: customSlotImages has ' + Object.keys(window.customSlotImages).length + ' images'; } }; reader.readAsDataURL(file); } function previewSite() { const data = getFormData(); const theme = themes[selectedTheme]; const services = getServiceOptions(data.serviceType); let images = JSON.parse(JSON.stringify(stockImages[data.serviceType])); // Override with custom uploaded images if (window.customSlotImages) { if (window.customSlotImages['hero']) images.hero = window.customSlotImages['hero']; if (window.customSlotImages['service1']) images.services[0] = window.customSlotImages['service1']; if (window.customSlotImages['service2']) images.services[1] = window.customSlotImages['service2']; if (window.customSlotImages['service3']) images.services[2] = window.customSlotImages['service3']; if (window.customSlotImages['service4']) images.services[3] = window.customSlotImages['service4']; if (window.customSlotImages['service5']) images.services[4] = window.customSlotImages['service5']; // Team images if (!images.team) images.team = []; if (window.customSlotImages['team1']) images.team[0] = window.customSlotImages['team1']; if (window.customSlotImages['team2']) images.team[1] = window.customSlotImages['team2']; // Project images if (!images.projects) images.projects = []; if (window.customSlotImages['project1']) images.projects[0] = window.customSlotImages['project1']; if (window.customSlotImages['project2']) images.projects[1] = window.customSlotImages['project2']; if (window.customSlotImages['project3']) images.projects[2] = window.customSlotImages['project3']; } // Generate services with images let servicesHTML = services.map((s, i) => `
${s}
${['🔧','⚡','🛠️','✅','🏠'][i]}
${s}
`).join(''); const heroOverlay = theme.name === 'Clean Professional' || theme.name === 'Vibrant Service' || theme.name === 'Friendly Local' ? 'rgba(255,255,255,0.85)' : 'rgba(0,0,0,0.5)'; const html = ` ${data.businessName || 'Your Business'} | ${data.serviceType.charAt(0).toUpperCase() + data.serviceType.slice(1)} in ${data.location} * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: '${data.headingFont}', system-ui, sans-serif; background: ${theme.bg}; color: ${theme.text}; line-height: 1.6; } header { background: rgba(0,0,0,0.2); padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; } .logo { font-size: 1.5rem; font-weight: 700; color: ${theme.accent}; } .hero { padding: 5rem 2rem; text-align: center; background: linear-gradient(${heroOverlay}, ${heroOverlay}), url(${images.hero}); background-size: cover; background-position: center; } .hero h1 { font-size: 3rem; margin-bottom: 1rem; } .hero p { font-size: 1.3rem; opacity: 0.9; } .services { max-width: 1200px; margin: 4rem auto; padding: 0 2rem; } .services h2 { text-align: center; margin-bottom: 2rem; font-size: 2rem; color: ${theme.accent}; } .service-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.5rem; } .cta { background: ${theme.accent}; color: white; padding: 4rem 2rem; text-align: center; } .cta h2 { margin-bottom: 1rem; } .phone { font-size: 2.5rem; font-weight: 700; } .contact { max-width: 1000px; margin: 4rem auto; padding: 3rem 2rem; background: #f8f9fa; color: #1a1a2e; } .contact h2 { text-align: center; margin-bottom: 1rem; font-size: 2rem; } .form-container { background: white; border-radius: 12px; padding: 2rem; margin: 2rem auto; max-width: 500px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .form-container h3 { margin-bottom: 1rem; color: #ff6b35; } .form-container input, .form-container select, .form-container textarea { width: 100%; padding: 0.8rem; margin-bottom: 1rem; border: 1px solid #ddd; border-radius: 6px; font-size: 1rem; font-family: inherit; } .form-container button { background: #ff6b35; color: white; border: none; padding: 1rem 2rem; border-radius: 6px; font-size: 1rem; font-weight: 600; cursor: pointer; width: 100%; } .form-container button:hover { background: #e55a2b; } .contact-info { text-align: center; margin-top: 2rem; padding-top: 2rem; border-top: 1px solid #ddd; } .contact-info p { margin: 0.5rem 0; font-size: 1.1rem; } footer { background: rgba(0,0,0,0.3); padding: 2rem; text-align: center; opacity: 0.7; }
📞 ${data.phone || '(555) 000-0000'}

Professional ${data.serviceType.charAt(0).toUpperCase() + data.serviceType.slice(1)} Services in ${data.location || 'Your City'}

Licensed, Insured, and Ready to Serve You

Our Services

${servicesHTML}

Our Team

Team Member 1

Team Member 2

Completed Projects

Project 1

Project 2

Project 3

Ready to Get Started?

📞 ${data.phone || '(555) 000-0000'}

Contact Us

Fill out the form below or call us directly

📬 Send Us a Message

📋 Request a Quote

Tell us about your project and we'll get back to you with a quote.

📞 ${data.phone || '(555) 000-0000'}

📧 ${data.email || 'info@yourbusiness.com'}

`; const iframe = document.getElementById('previewIframe'); iframe.srcdoc = html; } function getFormData() { return { businessName: document.getElementById('businessName').value, serviceType: document.getElementById('serviceType').value, location: document.getElementById('location').value, phone: document.getElementById('phone').value, email: document.getElementById('email').value, theme: selectedTheme, primaryColor: document.getElementById('primaryColor').value, headingFont: document.getElementById('headingFont').value }; } // Load client data from URL code let currentBuildId = null; // Global helper: hide business fields for demo mode function hideBusinessFields() { console.log('hideBusinessFields called'); alert('hideBusinessFields CALLED!'); const hideIds = ['businessName', 'serviceType', 'location', 'phone', 'email']; hideIds.forEach(id => { const input = document.getElementById(id); if (input) { input.style.display = 'none'; const group = input.closest('.form-group'); if (group) { group.style.display = 'none'; console.log('Hid: ' + id); } } }); const h2 = document.querySelector('.controls h2'); if (h2) h2.textContent = '🖼️ Customize Theme & Add Images'; const actions = document.querySelector('.controls .actions'); if (actions) actions.style.display = 'flex'; } async function loadClientFromCode() { // Load client data on page load if code param present const params = new URLSearchParams(window.location.search); const code = params.get('code'); const statusDiv = document.getElementById('debugStatus'); statusDiv.textContent = 'loadClientFromCode: ' + code; statusDiv.textContent = 'Code found: ' + code + ' - querying Airtable...'; // Ensure business fields are hidden for demo codes hideBusinessFields(); // Detect service type from code if no Airtable record const codeServiceMap = { 'plumbing': 'plumbing', 'plumber': 'plumbing', 'hvac': 'hvac', 'ac': 'hvac', 'heating': 'hvac', 'cool': 'hvac', 'roofing': 'roofing', 'roof': 'roofing', 'electrical': 'electrical', 'electric': 'electrical', 'pool': 'pool', 'painting': 'painting', 'paint': 'painting', 'pest': 'pest', 'pestcontrol': 'pest', 'cleaning': 'cleaning', 'clean': 'cleaning', 'landscaping': 'landscaping', 'landscape': 'landscaping' }; const codeLower = code.toLowerCase(); let detectedService = ''; const keys = Object.keys(codeServiceMap); for (let i = 0; i < keys.length; i++) { if (codeLower.indexOf(keys[i]) !== -1) { detectedService = codeServiceMap[keys[i]]; break; } } // Try to find client by Build ID (code) try { const resp = await fetch('/api/airtable?table=Website%20Builds?filterByFormula=({Build%20ID}=\'' + code + '\')', { headers: { 'Content-Type': 'application/json' } }); const data = await resp.json(); if (data.records && data.records.length > 0) { const fields = data.records[0].fields; currentBuildId = fields['Build ID']; // Pre-fill form if (fields['Business Name']) document.getElementById('businessName').value = fields['Business Name']; if (fields['Service Type']) document.getElementById('serviceType').value = fields['Service Type']; if (fields['Location']) document.getElementById('location').value = fields['Location']; if (fields['Phone']) document.getElementById('phone').value = fields['Phone']; if (fields['Email']) document.getElementById('email').value = fields['Email']; if (fields['Theme']) selectedTheme = fields['Theme']; if (fields['Primary Color']) document.getElementById('primaryColor').value = fields['Primary Color']; if (fields['Heading Font']) document.getElementById('headingFont').value = fields['Heading Font']; // Update image slots for this service type generateSlotUploads(); // Load existing images from Airtable try { const imgResp = await fetch('/api/airtable?table=Website%20Images?filterByFormula=({Build%20ID}=\'' + (currentBuildId || code) + '\')', { headers: { 'Content-Type': 'application/json' } }); const imgData = await imgResp.json(); if (imgData.records && imgData.records.length > 0) { if (!window.customSlotImages) window.customSlotImages = {}; const slotReverseMap = { 'hero': 'hero', 'service1': 'service1', 'service2': 'service2', 'service3': 'service3', 'service4': 'service4', 'service5': 'service5', 'about1': 'team1', 'about2': 'team2', 'job1': 'project1', 'job2': 'project2', 'job3': 'project3' }; for (let i = 0; i < imgData.records.length; i++) { const rec = imgData.records[i]; const imgType = rec.fields['Image Type']; const desc = rec.fields['Description']; const slot = slotReverseMap[imgType] || imgType; if (desc && desc.startsWith('data:')) { window.customSlotImages[slot] = desc; // Update preview const preview = document.getElementById('preview_' + slot); if (preview) { preview.innerHTML = '✅ Saved'; preview.style.color = '#27ae60'; } } } } } catch(e) { console.log('Error loading existing images:', e); } // Hide form fields, show only theme/font and image upload // Hide by finding the parent of specific input IDs // hide handled by hideBusinessFields hideBusinessFields(); return true; } } catch(e) { console.log('No client found for code:', code); } // If no Airtable record but detected service from code if (detectedService) { document.getElementById('serviceType').value = detectedService; document.getElementById('businessName').value = 'Demo ' + detectedService.charAt(0).toUpperCase() + detectedService.slice(1); generateSlotUploads(); // Hide form fields, show only theme/font and image upload const hideIds = ['businessName', 'serviceType', 'location', 'phone', 'email']; hideIds.forEach(id => { const input = document.getElementById(id); if (input && input.parentElement.classList.contains('form-group')) { input.parentElement.style.display = 'none'; } }); document.querySelector('.controls h2').textContent = '🖼️ Customize Theme & Add Images'; // Show actions for image upload document.querySelector('.controls .actions').style.display = 'flex'; return true; } return false; } async function submitBuild() { const data = getFormData(); const params = new URLSearchParams(window.location.search); const urlCode = params.get('code'); const buildId = currentBuildId || urlCode || 'BUILD-' + Date.now(); // Save to Airtable try { let response; if (currentBuildId) { // Update existing build response = { ok: true }; } else { response = await fetch('/api/airtable?table=Website%20Builds', { method: 'POST', headers: { 'Authorization: Bearer (use proxy), 'Content-Type': 'application/json' }, body: JSON.stringify({ fields: { 'Build ID': buildId, 'Business Name': data.businessName, 'Service Type': data.serviceType, 'Location': data.location, 'Phone': data.phone, 'Email': data.email, 'Theme': data.theme, 'Primary Color': data.primaryColor, 'Heading Font': data.headingFont, 'Status': 'Pending' } }) }); } // Save custom images to Airtable as base64 text let imagesSaved = 0; const debugInfo = document.getElementById('debugInfo') || document.createElement('div'); debugInfo.id = 'debugInfo'; debugInfo.style.cssText = 'position:fixed;bottom:10px;left:10px;background:#fff;color:#000;padding:10px;z-index:9999;font-size:12px;max-width:300px;word-break:break-all;'; document.body.appendChild(debugInfo); debugInfo.innerHTML = 'Debug: customSlotImages has ' + (window.customSlotImages ? Object.keys(window.customSlotImages).length : 0) + ' images'; if (window.customSlotImages) { const slotMapping = { 'hero': 'hero', 'service1': 'service1', 'service2': 'service2', 'service3': 'service3', 'service4': 'service4', 'service5': 'service5', 'team1': 'about1', 'team2': 'about2', 'project1': 'job1', 'project2': 'job2', 'project3': 'job3' }; const slots = ['hero', 'service1', 'service2', 'service3', 'service4', 'service5', 'team1', 'team2', 'project1', 'project2', 'project3']; for (let i = 0; i < slots.length; i++) { const slot = slots[i]; if (window.customSlotImages[slot]) { try { const airtableSlot = slotMapping[slot] || slot; // Save base64 image data to Airtable const imgResp = await fetch('/api/airtable?table=Website%20Images', { method: 'POST', headers: { 'Authorization: Bearer (use proxy), 'Content-Type': 'application/json' }, body: JSON.stringify({ fields: { 'Build ID': buildId, 'Image Type': airtableSlot, 'Description': window.customSlotImages[slot].substring(0, 1000), // truncate for debug 'Status': 'Submitted' } }) }); const imgText = await imgResp.text(); alert('Image save response: ' + imgResp.status + ' - ' + imgText.substring(0, 100)); if (imgResp.ok) imagesSaved++; } catch(e) { console.log('Image save error:', e); } } } } alert('Saved ' + imagesSaved + ' images to Airtable!'); if (response.ok) { document.getElementById('buildId').textContent = 'Build ID: ' + buildId; document.getElementById('overlay').classList.add('show'); document.getElementById('successMessage').classList.add('show'); } else { alert('Error saving. Please try again.'); } } catch (e) { // Fallback: show success anyway for demo document.getElementById('buildId').textContent = 'Build ID: ' + buildId + ' (Demo Mode)'; document.getElementById('overlay').classList.add('show'); document.getElementById('successMessage').classList.add('show'); } } function closeSuccess() { document.getElementById('overlay').classList.remove('show'); document.getElementById('successMessage').classList.remove('show'); } // Initialize - run immediately (script is at end of body, DOM ready) (function() { const statusDiv = document.getElementById('debugStatus'); const params = new URLSearchParams(window.location.search); const code = params.get('code'); statusDiv.textContent = code ? 'Code: ' + code : 'No code'; if (code) { // Hide business fields FIRST, then load client hideBusinessFields(); loadClientFromCode(); } updateImagePreview(); generateSlotUploads(); })(); // Load custom images from localStorage (from stock-image-manager) function loadCustomImages() { const serviceType = document.getElementById('serviceType').value; const slots = ['hero', 'service1', 'service2', 'service3', 'service4', 'service5', 'team1', 'team2', 'project1', 'project2', 'project3']; slots.forEach(slot => { const key = `custom_${serviceType}_${slot}`; const customUrl = localStorage.getItem(key); if (customUrl) { // Update preview if exists const preview = document.querySelector(`[data-slot="${slot}"]`); if (preview) { preview.src = customUrl; } } }); } // Load custom images when service type changes document.getElementById('serviceType').addEventListener('change', loadCustomImages); loadCustomImages(); // Also run on init // Custom images handling const customImages = []; function handleCustomImages(input) { const list = document.getElementById('customImagesList'); list.innerHTML = ''; for (const file of input.files) { const reader = new FileReader(); reader.onload = function(e) { const div = document.createElement('div'); div.style.cssText = 'display: inline-block; margin: 5px; padding: 5px; background: rgba(39,174,96,0.2); border-radius: 4px; font-size: 0.75rem;'; div.innerHTML = '✅ ' + file.name; list.appendChild(div); }; reader.readAsDataURL(file); } } function openThemePreview() { document.getElementById('themePreviewModal').style.display = 'block'; document.body.style.overflow = 'hidden'; } function closeThemePreview() { document.getElementById('themePreviewModal').style.display = 'none'; document.body.style.overflow = 'auto'; } function selectThemeAndClose(theme) { selectThemeById(theme); closeThemePreview(); } function selectThemeById(theme) { document.querySelectorAll('.theme-option').forEach(t => t.classList.remove('selected')); document.querySelector('[data-theme="' + theme + '"]').classList.add('selected'); selectedTheme = theme; }